#include "test.h"

#include  <sys/types.h>
#include <sys/wait.h>
#include "../xml/XMLParse.h"
#include "../dtd/DTDParse.h"
#include "../validator.h"

#define RUN_TEST(name) run_test(name, #name)

/*** Tests des fonctions de test ***/
int successer(){
	return 1;
}

int failer(){
	return 0;
}

int segfaulter(){
	*((int*)0) = 1;
	return 0;
}

/*** Tests de la fonction xmlparse() ***/
int xml_valide_dtd_indiquee(){
	Element *xml;
	char *dtd_path;
	xmlin = fopen("test/rap2.xml", "r");
	if ((xmlparse(&xml, &dtd_path) == 0) && strcmp(dtd_path, "rap2.dtd") == 0)
		return 1;
	return 0;
}

int xml_valide_dtd_non_indiquee(){
	Element *xml;
	char *dtd_path;
	xmlin = fopen("test/freeXML.xml", "r");
	if ((xmlparse(&xml, &dtd_path) == 0) && strcmp(dtd_path, "") == 0)
		return 1;
	return 0;
}

int xml_non_valide(){
	Element *xml;
	char *dtd_path;
	xmlin = fopen("test/invalid.xml", "r");
	if (xmlparse(&xml, &dtd_path) >= 0)
		return 1;
	return 0;
}

/*** Tests de la fonction dtdparse() ***/
int dtd_complexe_valide(){
	DTD* dtd;
	dtdin = fopen("test/rap4.dtd", "r");
	if (dtdparse(&dtd) == 0)
		return 1;
	return 0;
}

int dtd_simple_valide(){
	DTD *dtd;
	dtdin = fopen("test/rap1.dtd", "r");
	if (dtdparse(&dtd) == 0)
		return 1;
	return 0;
}

int dtd_invalide(){
	DTD *dtd;
	dtdin = fopen("test/invalid.dtd", "r");
	if (dtdparse(&dtd) > 0)
		return 1;
	return 0;
}

/*** Tests de la fonction validate_xml() ***/
int xml_introuvable(){
	if(validate_xml("test/doesnotexists.xml","") == XML_NOT_FOUND)
		return 1;
	return 0;
}

int dtd_introuvable(){
	if(validate_xml("test/freeXML.xml", "test/doesnotexists.dtd") == DTD_NOT_FOUND)
		return 1;
	return 0;
}

int dtd_indiquee_dans_xml(){
	if(validate_xml("test/rap1.xml", "") != DTD_NOT_FOUND)
		return 1;
	return 0;
}

int dtd_override(){
	if(validate_xml("test/rap1.xml", "test/doesnotexists.dtd") == DTD_NOT_FOUND)
		return 1;
	return 0;
}

int sans_dtd(){
	if(validate_xml("test/freeXML.xml","") == XML_VALID)
		return 1;
	return 0;
}

int rap1(){
	if(validate_xml("test/rap1.xml","") == OK)
		return 1;
	return 0;
}

int rap2_xml_non_conforme(){
	if(validate_xml("test/rap2.xml", "") == XML_NOT_CONFORM)
		return 1;
	return 0;
}

int rap3_introuvable(){
	if(validate_xml("test/rap3.xml", "") == XML_NOT_FOUND)
		return 1;
	return 0;
}

int w3c_example(){
	if(validate_xml("test/note_ex_dtd.xml", "") == OK)
		return 1;
	return 0;
}

int w3c_example_simplifie(){
	if(validate_xml("test/note_ex_dtd_simple.xml", "") == OK)
		return 1;
	return 0;
}

int invalid_xml(){
	if(validate_xml("test/invalid.xml", "") == XML_INVALID)
		return 1;
	return 0;
}

int invalid_dtd(){
	if(validate_xml("test/rap1.xml", "test/invalid.dtd") == DTD_INVALID)
		return 1;
	return 0;
}

int test_xml_avant_dtd(){
	if(validate_xml("test/invalid.xml", "test/invalid.dtd") == XML_INVALID)
		return 1;
	return 0;
}

int xml_attlist_invalide(){
	if(validate_xml("test/note_ex_dtd_simple.xml", "test/note_attlist.dtd") == XML_NOT_CONFORM)
		return 1;
	return 0;
}

void run_test(TestFct *fct, string name) {
	pid_t test_pid = fork();
	if(test_pid == 0)
	{
		freopen( "/dev/null", "w", stdout );
		freopen( "/dev/null", "w", stderr );
		_exit((*fct)());
	}
	else
	{
		int status;
		wait(&status);
		freopen( "/dev/tty", "w", stdout );
		freopen( "/dev/tty", "w", stderr );
		string result = "";
		if(WIFEXITED(status) == 0)
			result = "anormal exit";
		else if(WEXITSTATUS(status) == 1)
			result = "success";
		else
			result = "fail";
		string points("");
		points.resize(50 - name.size(), '.');
		cout << name << points << result << endl;
	}
}

int main() {
	cout << "==== Méta" << endl;
	RUN_TEST(successer);
	RUN_TEST(failer);
	RUN_TEST(segfaulter);
	cout << endl << "==== XML unitaire (fonction xmlparse())" << endl;
	RUN_TEST(xml_valide_dtd_indiquee);
	RUN_TEST(xml_valide_dtd_non_indiquee);
	RUN_TEST(xml_non_valide);
	cout << endl << "==== DTD unitaire (fonction dtdparse())" << endl;
	RUN_TEST(dtd_simple_valide);
	RUN_TEST(dtd_complexe_valide);
	RUN_TEST(dtd_invalide);
	cout << endl << "==== Comportement général (fonction validate_xml)" << endl;
	RUN_TEST(xml_introuvable);
	RUN_TEST(dtd_introuvable);
	RUN_TEST(invalid_xml);
	RUN_TEST(invalid_dtd);
	RUN_TEST(test_xml_avant_dtd);
	RUN_TEST(dtd_indiquee_dans_xml);
	RUN_TEST(dtd_override);
	RUN_TEST(sans_dtd);
	cout << endl << "==== Cas réel avec validation" << endl;
	RUN_TEST(rap1);
	RUN_TEST(rap2_xml_non_conforme);
	RUN_TEST(rap3_introuvable);
	RUN_TEST(xml_attlist_invalide);
	RUN_TEST(w3c_example);
	RUN_TEST(w3c_example_simplifie);
	return 0;
}
